package com.ycb.concurrency.limitation.rate;

import lombok.extern.slf4j.Slf4j;

/**
 * 固定时间窗口限流
 */
@Slf4j
public class FixedTimeRateLimiter implements RateLimiter {

    // 当前累计请求量
    private int requestCount = 0;
    // 固定时间窗口请求量限制
    private int maxCount = 10;
    /*
     当前固定时间窗口右边界
     (left, right]  判断当前时间和边界大小，若 current > right，窗口累计值清零，窗口向右移动
     */
    private long fixedTimeBorder = 0;
    // 固定窗口大小
    private long fixedTimeSize = 1000;

    /**
     * 固定时间速率限制器
     * @param maxCount  最大请求数
     * @param fixedTimeSize  固定时间(毫秒)
     */
    public FixedTimeRateLimiter(int maxCount, int fixedTimeSize) {
        this.maxCount = maxCount;
        this.fixedTimeSize = fixedTimeSize;
    }

    private void refreshWindow(long now) {
        // 考虑请求间隔超过窗口大小
        if (fixedTimeBorder < now){
            long num ;
            if (now % fixedTimeSize == 0) {
                num = now / fixedTimeSize;
            }else{
                num = now / fixedTimeSize + 1;
            }
            fixedTimeBorder = num * fixedTimeSize;
        }
        requestCount = 0;
        log.warn("fixed time window reload timestamp:" + now + " fixedTimeBorder:" + fixedTimeBorder);
    }

    @Override
    public synchronized boolean tryAcquire() {
        long now = System.currentTimeMillis();
        if (fixedTimeBorder < now) {
            refreshWindow(now);
        }
        if (requestCount < maxCount) {
            requestCount++;
            log.info("try acquire success! current requestCount:" + requestCount + " current:" + now + " fixedTimeBorder:" + fixedTimeBorder);
            return true;
        } else {
            log.error("try acquire fail. current:" + now + " fixedTimeBorder:" + fixedTimeBorder);
            return false;
        }
    }
}
